﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;

namespace SimpleRayTracer
{
    public partial class TracerForm : Form
    {
        private Bitmap image;
        private int countObject = 0;
        private List<ObjectContainer> objectContList = new List<ObjectContainer>();
        private System.Drawing.Imaging.ImageFormat format = System.Drawing.Imaging.ImageFormat.Png;
        private Screen screen = new Screen();
        TracerMain tracer = new TracerMain();

        private event EventHandler OnProgressChanged;
        private DataPacketGUI dataPacketGui = new DataPacketGUI();

        public TracerForm()
        {
            CheckForIllegalCrossThreadCalls = false;
            InitializeComponent();

            screen.Height = 480;
            screen.Width = 480;

            OnProgressChanged += new EventHandler(ProgressChanged);
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            if (SaveOutput())
            {
                statusBox.Text = "File save done...";
            }
            else
            {
                statusBox.Text = "File save error!";
            }
        }

        private bool SaveOutput()
        {
            if (image != null)
            {
                SaveFileDialog fileDialog = new SaveFileDialog();
                fileDialog.Filter = "Image files (*.png)|*.png";

                DialogResult fileResult = fileDialog.ShowDialog();

                if (fileResult == DialogResult.OK)
                {
                    try
                    {
                        image.Save(fileDialog.FileName + "." + format.ToString().ToLower(), format);
                    }
                    catch
                    {
                        return false;
                    }

                }

                return true;

            }
            return false;
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            dataPacketGui.tracerProgress = 0.0;
            dataPacketGui.statusFOV = 0.0;

            image = tracer.InitTracer(screen.Width, screen.Height, pictureBox1.Width, pictureBox1.Height);

            pictureBox1.Image = image;

            tracer.StartTracer(double.Parse(cuX.Text), double.Parse(cuY.Text), double.Parse(cuZ.Text),
                        double.Parse(ctX.Text), double.Parse(ctY.Text), double.Parse(ctZ.Text),
                        double.Parse(vX.Text), double.Parse(vY.Text), double.Parse(vZ.Text),
                        objectContList, double.Parse(lcX.Text), double.Parse(lcY.Text), double.Parse(lcZ.Text));

            Thread updateThrd = new Thread(UpdateGui);
            updateThrd.Start();
        }

        private void btnAddSphere_Click(object sender, EventArgs e)
        {
            countObject++;

            int colR = 0;
            int colG = 0;
            int colB = 0;

            Random rndC = new Random(10);
            colR = rndC.Next(100, 200);
            colG = rndC.Next(100, 200);
            colB = rndC.Next(100, 200);

            Sphere sphere = new Sphere(new Vector3D(
                double.Parse(sphX.Text),
                double.Parse(sphY.Text),
                double.Parse(sphZ.Text)),
                double.Parse(sphR.Text),
                colR,
                colG,
                colB);

            ObjectContainer sphCont = new ObjectContainer();
            sphCont.Name = countObject.ToString() + " Sphere";
            sphCont.Object = sphere;
            sphCont.objType = ObjType.Sphere;

            objectContList.Add(sphCont);
            listBox1.Items.Add(sphCont.Name + " - " + sphCont.objType.ToString());
        }

        private void btnAddTriangle_Click(object sender, EventArgs e)
        {
            countObject++;

            int colR = 0;
            int colG = 0;
            int colB = 0;

            Random rndC = new Random(10);
            colR = rndC.Next(100, 200);
            colG = rndC.Next(100, 200);
            colB = rndC.Next(100, 200);

            Triangle triangle = new Triangle(
                new Vector3D(double.Parse(Tri1X.Text), double.Parse(Tri1Y.Text), double.Parse(Tri1Z.Text)), 
                new Vector3D(double.Parse(Tri2X.Text), double.Parse(Tri2Y.Text), double.Parse(Tri2Z.Text)),
                new Vector3D(double.Parse(Tri3X.Text), double.Parse(Tri3Y.Text), double.Parse(Tri3Z.Text)),
                colR,
                colG,
                colB);

            ObjectContainer triCont = new ObjectContainer();
            triCont.Name = countObject.ToString() + " Triangle";
            triCont.Object = triangle;
            triCont.objType = ObjType.Triangle;

            objectContList.Add(triCont);
            listBox1.Items.Add(triCont.Name + " - " + triCont.objType.ToString());
        }

        private void UpdateGui()
        {
            bool exit = false;
            

            while ((this.IsDisposed != true) && (tracer != null) && (!exit))
            {
                Thread.Sleep(100);

                dataPacketGui.tracerProgress = tracer.tracerProgress;
                dataPacketGui.statusFOV = tracer.statusFOV;


                this.OnProgressChanged(dataPacketGui, new EventArgs());

                if (dataPacketGui.tracerProgress == 100)
                {
                    pictureBox1.Image = image;
                    exit = true;
                }
            }
        }

        void ProgressChanged(object sender, EventArgs e)
        {
            DataPacketGUI tempOutput = (DataPacketGUI)sender;

            statusBox.Text = tempOutput.tracerProgress.ToString() + "%";
            statusBox.Refresh();

            //tbFOV.Text = tempOutput.statusFOV.ToString();
            //tbFOV.Refresh();
        }

        private void btnReset_Click(object sender, EventArgs e)
        {
            objectContList.Clear();
            listBox1.Items.Clear();
            dataPacketGui.tracerProgress = 0.0;
            dataPacketGui.statusFOV = 0.0;
            countObject = 0;
        }

        private void btnLoadFile_Click(object sender, EventArgs e)
        {
            FileDialog fileDialog = new OpenFileDialog();

            fileDialog.Filter = "OBJ 3D|*.obj";

            if (fileDialog.ShowDialog() == DialogResult.OK)
            {

            }
        }

    }
}
